/*****************************************************
 * File:            Onlt_RandomWalk_FSM.cs
 * Description:     Online Random Walk Testing
 * By:              Ali Khalili (khalili DOT ir AT gmail DOT com)
 * Project:         Testing Engine
 * Namespece		MBT.Conformance.OfflineTesting
 * License:
 * Changes:
 * 					-14 Aug 2014: bug fixed (dead state was not considered)
 * ToDo: 
 * 				    make it available also for IAs and other authomata
 *****************************************************/
using System;
using SMLib.Automata.MM;
using System.Collections.Generic;
using MBT.Base;

namespace MBT.Conformance.OnlineTesting
{
	/// <summary>
	/// Offline Test Case Generation - random walk policy
	/// <remarks>
	/// There is a notable difference between online FSM-based and ioco-based 
	/// random walk: the FSM-based method is available for any automata
	/// and the assumption is existence of an edge means it would be runnable
	/// (which means, if there is an observable event, you will always be able
	/// to see it) where as in online ioco-based, it follows ioco theory.
	/// </remarks>
	/// </summary>
	public class Onlt_RandomWalk_FSM
	{		
		/// <summary>
		/// Gets the number of generated tests.
		/// </summary>
		public int NumberOfGeneratedTests
		{
			get{
				return numbTest;
			}
		}
		
		int numbTest;
		MealyMachine model;
		int MAX_NUMBER_OF_TEST;
		int LENGHT_COEF;
		Random rnd;
		
		/// <summary>
		/// Initializes a new instance of the 
		/// <see cref="MBT.Conformance.OfflineTesting.Onlt_RandomWalk_FSM"/> class.
		/// </summary>
		/// <param name='model'>
		/// The Model to be used for test case generation
		/// </param>
		public Onlt_RandomWalk_FSM (MealyMachine model)
		{
			if(!LibSetting.IsInitialized)
			{
				Console.Write("\nWarning: The AIDE configuration is not initialized! Initializing it...\n");
				LibSetting.Init();
				Console.WriteLine("Done!");
				//throw new Exception("Error: the MBT library is not initialized!");
			}
			LENGHT_COEF = int.Parse(LibSetting.ConfOf("Testing.RandomWalk.LengthCoef"));
			numbTest=0;
			this.model=model;
			rnd=new Random();
			MAX_NUMBER_OF_TEST = LibSetting.SuiteSize;			
		}
		
		//public static bool AlsoUseDisables = true;

		/// <summary>
		/// Enumerates the test cases.
		/// </summary>
		/// <returns>
		/// The test cases.
		/// </returns>
		public IEnumerable<List<MealyMachine.Mealy_Transition>> EnumerateTestCases()
		{
			//Console.WriteLine("LENGHT_COEF="+LENGHT_COEF+"\nMAX_NUMBER_OF_TEST="+MAX_NUMBER_OF_TEST);			
			int numberOfGeneratedTest=0;
			List<MealyMachine.Mealy_Transition> currentTest=new List<MealyMachine.Mealy_Transition> ();
			MealyMachine.Mealy_State currentState;
			MealyMachine.Mealy_Transition selectedEdge=null;
			do
			{
				currentState=model.InitialState;
				currentTest.Clear();
				int len=model.Size +  LENGHT_COEF * rnd.Next(model.Size+1);
				for(int i=0;i<len;i++)
				{
					//* BUG FIXED: we cannot go further from dead states!
					if(currentState.Transitions.Count==0)
						break;
					selectedEdge = currentState.Transitions[rnd.Next(currentState.Transitions.Count)];
					currentState = selectedEdge.Destination;
					currentTest.Add(selectedEdge);
				}
				numberOfGeneratedTest++;
				numbTest++;
				yield return currentTest;
				
			}while(numberOfGeneratedTest<MAX_NUMBER_OF_TEST);			
		}
	}
}

